import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Timer;

//自己创建一个定时器
class MyTimerTask implements Comparable<MyTimerTask>{//优先级队列要能比较大小
    //通过 implements 或者持有 成员变量 都是可以的
    private Runnable runnable;
    //什么时候进行执行,此时的 time 不是 delay ,只是一个 ms 级别的时间戳(绝对时间)
    private long time;

    public MyTimerTask(Runnable runnable, long delay){
        this.runnable = runnable;
        this.time = System.currentTimeMillis()+delay;//获取绝对时间,系统时间+设定的等待时间
    }
    public void run(){
        runnable.run();
    }
    public long getTime(){
        return time;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        //按照时间进行比较,最终构建小堆
        return (int) (this.time-o.time);//小堆
        //return (int) (o.time-this.time)//大堆
    }
}
class MyTimer{
    private PriorityQueue<MyTimerTask> timerTasks = new PriorityQueue<>();
    public void schedule(Runnable runnable,long delay){
        //这个线程进行了入队列操作
        synchronized (locker){
            MyTimerTask task = new MyTimerTask(runnable,delay);
            timerTasks.offer(task);
            locker.notify();//当有新的任务,就重新唤醒一下
        }
    }

    private Object locker = new Object();

    public MyTimer(){
        //这个线程不停的扫描上述的队列队首元素,确定是否要执行任务
        Thread t = new Thread(()->{
            //这个线程进行了出队列操作
            try {
                while(true){
                    synchronized (locker){
                        if(timerTasks.size()==0){
                            //为空就不会执行后续操作
                            locker.wait();
                            //直到生产者线程,添加的新的任务,才会使用 notify 去启动wait
                        }
                        MyTimerTask task = timerTasks.peek();
                        long curTime = System.currentTimeMillis();
                        if(curTime>=task.getTime()){
                            //时间到了
                            task.run();
                            timerTasks.poll();//删除掉已经执行了的
                        }else{
                            //时间没到
                            locker.wait(task.getTime()-curTime);//按照时间差来等待,task.getTime()是要启动的时间,curTime是进行判定时的系统时间
                            //此时如果有新任务的加入,也会唤醒wait      但是如果没有,到了wait设定时间,他也会自然解除wait状态
                        }
                    }
                }
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        });
        t.start();
    }
}
public class Demo4 {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 3000");
            }
        },3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 2000");
            }
        },2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 1000");
            }
        },1000);
    }
}
